/*
 * Copyright (C) 2015 Brent Marriott
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hookedonplay.decoviewlib.charts;

import com.hookedonplay.decoviewlib.util.RectFutil;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.render.SweepShader;
import ohos.agp.utils.Color;
import ohos.agp.utils.Matrix;
import org.jetbrains.annotations.NonNls;

public abstract class ArcSeries extends ChartSeries {
    /**
     * Angle that the arc starts
     */
    protected float mArcAngleStart;
    /**
     * Sweep angle starts at {@link #mArcAngleStart}
     */
    protected float mArcAngleSweep;

    ArcSeries(@NonNls SeriesItem seriesItem, int totalAngle, int rotateAngle) {
        super(seriesItem, totalAngle, rotateAngle);
    }

    /**
     * Draw the arc in the current state
     *
     * @param canvas Canvas to draw onto
     */
    abstract void drawArc(Canvas canvas);

    /**
     * Draw this arc in the current position calculated by the ValueAnimator.
     *
     * @param canvas Canvas used to draw
     * @param bounds Bounds to be used to draw the arc
     * @return true is draw view has been handled
     */
    @Override
    public boolean draw(Canvas canvas, RectFutil bounds) {
        if (super.draw(canvas, bounds)) {
            return true;
        }

       final float endPos = calcCurrentPosition(mPositionStart, mPositionEnd, mSeriesItem.getMinValue(),
                        mSeriesItem.getMaxValue(), mPercentComplete);
        mArcAngleSweep = adjustSweepDirection(verifyMinSweepAngle(endPos * mAngleSweep));
        mArcAngleStart = mAngleStart;

        if (mSeriesItem.getDrawAsPoint()) {
            mArcAngleStart = adjustDrawPointAngle(mArcAngleSweep);
            mArcAngleSweep = adjustSweepDirection(getMinSweepAngle());
        } else if (mArcAngleSweep == 0) {
            return true;
        }

        return false;
    }

    /**
     * Build a gradient if required. This must be executed every time the bounds changes
     */
    protected void applyGradientToPaint() {
        if (Color.alpha(mSeriesItem.getSecondaryColor()) != 0) {
            SweepShader gradient;
            if (mAngleSweep < 360) {
                /**
                 * When we have less than a full circle we change the style of gradient so that
                 * the two colors start at the same point. The two provided colors meet rather than
                 * a fade the complete circumference. A matrix is rotated so the meeting of the
                 * two colors occurs in the middle of the gap when the part circle is not drawn
                 */
                final Color[] colors = {new Color(mSeriesItem.getColor()), new Color(mSeriesItem.getSecondaryColor())};
                final float[] positions = {0, 1};
                gradient =
                        new SweepShader(
                                mBounds.getHorizontalCenter(),
                                mBounds.getVerticalCenter(),
                                colors,
                                positions);
                Matrix gradientRotationMatrix = new Matrix();
                gradientRotationMatrix.preRotate(
                        mAngleStart - ((360f - mAngleSweep) / 2),
                        mBounds.getHorizontalCenter(),
                        mBounds.getVerticalCenter());
                gradient.setShaderMatrix(gradientRotationMatrix);
            } else {
                /**
                 * Drawing a gradient around the complete circumference of the circle. This
                 * gradient fades gently between the two colors.
                 */
                final Color[] colors = {
                    new Color(mSeriesItem.getSecondaryColor()),
                    new Color(mSeriesItem.getColor()),
                    new Color(mSeriesItem.getSecondaryColor())
                };
                final float[] positions = {0, 0.5f * (mAngleSweep / 360f), 1};
                gradient =
                        new SweepShader(mBounds.getHorizontalCenter(), mBounds.getVerticalCenter(), colors, positions);
            }

            mPaint.setShader(gradient, Paint.ShaderType.LINEAR_SHADER);
        }
    }
}